package fanshe;
import org.junit.Test;

import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;

/**
 * 利用反射读取字段值
 * getFields()：获得本类及其父类所有以public修饰的字段
 * getDeclaredFields()：获得某个类的所有声明的字段，即包括public、private和protected，但是不包括父类的申明字段。
 */
public class CheckField {

	@Test
	public void test01() throws Exception {
		Object e = new Employee("lujieni", 9000);
		PropertyDescriptor pd = new PropertyDescriptor("salary", e.getClass());
		Object value = pd.getReadMethod().invoke(e);
		System.out.println(value);
	}

	@Test
	public void test02() throws Exception{
		Employee employee = new Employee("lujieni", 9000);
		employee.setHellos(Arrays.asList(new Hello("11"), new Hello("12")));
		PropertyDescriptor pd = new PropertyDescriptor("hellos", employee.getClass());
		Object invoke = pd.getReadMethod().invoke(employee);
		if(invoke instanceof Collection){
			for(Object o : (Collection)invoke){
				pd = new PropertyDescriptor("age", o.getClass());
				invoke = pd.getReadMethod().invoke(o);
				System.out.println(invoke);
			}
		}

	}

	@Test
	public void test03() throws Exception{
		Employee e = new Employee("lujieni", 9000);
		testGetFieldValueByReflect(e);
	}

	@Test
	public void test04() throws Exception{
		testGetStaticFieldValueByReflect();
	}

	/**
	 * 对象拷贝(利用PropertyDescriptor)
	 */
	@Test
	public void test05() throws IntrospectionException, InvocationTargetException, IllegalAccessException, InstantiationException {
		Employee e = new Employee("lujieni", 9000);
		Employee a = e.getClass().newInstance();
		for (Field field : e.getClass().getDeclaredFields()) {
			PropertyDescriptor pd = new PropertyDescriptor(field.getName(), e.getClass());
			Object result = pd.getReadMethod().invoke(e);
			field.setAccessible(true);
			field.set(a, result); // field.set(a, result); 给哪个类设置, 设置的值是啥
		}
		System.out.println(a);
	}





	public void testGetFieldValueByReflect(Object model) throws Exception {
		for (Field field : model.getClass().getDeclaredFields()) {
			if(!field.isAccessible()){
				field.setAccessible(true); // 让我们在用反射时访问私有变量
			}
			System.out.println(field.getName() + ":" + field.get(model));
		}
	}

	/**
	 * 静态变量是在类的实例化之前就进行了初始化（类的初始化阶段），
	 * 所以静态变量是跟着类本身走的，跟具体的对象无关，所以我们获取变量就不需要传入对象，直接传入null即可：
	 * @throws Exception
	 */
	public void testGetStaticFieldValueByReflect() throws Exception{
		Field field = Hello.class.getDeclaredField("name");
		field.setAccessible(true);
		String s = (String)field.get(null);
		System.out.println(s);
	}

	private Object findValueByFieldName(Object object, String fieldName) throws NoSuchFieldException,
			IntrospectionException, InvocationTargetException, IllegalAccessException {
		Class clazz = object.getClass();
		Field field = clazz.getDeclaredField(fieldName);
		field.setAccessible(true);
		PropertyDescriptor descriptor = new PropertyDescriptor(fieldName, clazz);
		Object property = descriptor.getReadMethod().invoke(object);
		return property;
	}

}

class Hello{

	private static String name = "static";

	private String age;

	public Hello(String age){
		this.age = age;
	}

	public String getAge() {
		return age;
	}

	public void setAge(String age) {
		this.age = age;
	}
}
class Person{

	private String name;
	
	public Person(String name) {
		this.name = name;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
}

class Employee extends Person{
	
	private double salary;

	private List<Hello> hellos;
	
	public Employee(String name, double salary) {
		super(name);
		this.salary = salary;
	}

	public Employee(){
		super(null);
	}

	public double getSalary() {
		return salary;
	}

	public void setSalary(double salary) {
		this.salary = salary;
	}

	public List<Hello> getHellos() {
		return hellos;
	}

	public void setHellos(List<Hello> hellos) {
		this.hellos = hellos;
	}
}




